package com.atguigu.stack;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;

//逆波兰表达式实现计算器
public class RpolishNotation {
    public static void main(String[] args) {
        //定义一个中缀表达式
        String inExpression = "1 + ( 2 * ( 2 + 3 ) / 5 )";

        ArrayList<String> list = reserExpression(inExpression);
        String expression = "";
        for (String s : list) {
            expression = expression + s + " ";
        }
        RpolishNotation rpl = new RpolishNotation();
        ArrayList<String> strings = rpl.strToList(expression);
        Stack<String> stackOpr = new Stack<>();
        int num1 = 0;
        int num2 = 0;
        for (String string : strings) {
            if (string.matches("\\d+")) {
                stackOpr.push(string);
            } else {
                num1 = Integer.parseInt(stackOpr.pop());
                num2 = Integer.parseInt(stackOpr.pop());
                int cal = rpl.cal(num1, num2, string);
                stackOpr.push(cal + "");
            }
        }
        System.out.printf("输出结果为%d", Integer.parseInt(stackOpr.pop()));

    }

    //将表达式转变为ArrayList
    public static ArrayList<String> strToList(String str) {
        String[] split = str.split(" ");
        ArrayList<String> strings = new ArrayList<>();
        for (String s : split) {
            strings.add(s);
        }
        return strings;
    }

    public int cal(int num1, int num2, String c) {
        int res = 0;
        switch (c) {
            case "+":
                res = num1 + num2;
                break;
            case "-":
                res = num2 - num1;
                break;
            case "*":
                res = num1 * num2;
                break;
            case "/":
                res = num2 / num1;
                break;
        }
        return res;
    }

    public static ArrayList<String> reserExpression(String str) {
        ArrayList<String> strings = strToList(str);
        //符号栈
        Stack<String> stack = new Stack<>();

        //定义存储结果集合
        ArrayList<String> strList = new ArrayList<>();

        String shuzi = "";
        for (String string : strings) {
            //判断为符号
            if (string.charAt(0) < 48 || string.charAt(0) > 57) {
                if (shuzi != "") {
                    strList.add(shuzi);
                    shuzi = "";
                }
                //判断符号优先级
                while (true) {
                    if (string.equals("(")) {
                        stack.push(string);
                        break;
                    }
                    if (stack.isEmpty()) {
                        stack.push(string);
                        break;
                    }
                    if (stack.peek().equals("(")) {
                        stack.push(string);
                        break;
                    }
                    if (string.equals(")")) {
                        while (true) {
                            String strPop = stack.pop();
                            if (strPop.equals("(")) {
                                break;
                            }
                            strList.add(strPop);
                        }
                        break;
                    }

                    if (operPriority(string) <= operPriority(stack.peek())) {
                        strList.add(stack.peek());
                        stack.pop();
                    } else {
                        stack.push(string);
                        break;
                    }

                }
            } else {
                shuzi = shuzi + string;
            }
        }
        if (shuzi !=""){
            strList.add(shuzi);
        }
        while (stack.size() > 0) {
            strList.add(stack.pop());
        }
        return strList;
    }

    public static int operPriority(String str) {
        if (str.equals("+") || str.equals("-")) {
            return 1;
        } else if (str.equals("*") || str.equals("/")) {
            return 2;
        } else {
            throw new RuntimeException("输入符号有误，无法识别");
        }
    }
}
